home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Amiga Plus 2004 #11
/
Amiga Plus CD - 2004 - No. 11.iso
/
AmiSoft
/
Dev
/
misc
/
LOCCounter.lha
/
LOCCounter
/
src
/
SourceCode.cpp
< prev
next >
Wrap
C/C++ Source or Header
|
2004-08-18
|
5KB
|
233 lines
/****************************************************************************
*
* $RCSfile: SourceCode.cpp $
* $Revision: 2.14 $
* $Date: 2004/08/18 21:46:43 $
* $Author: ssolie $
*
*****************************************************************************
*
* Copyright (c) 2004 Steven Solie. All Rights Reserved.
*
*****************************************************************************
*
* SourceCode component
*/
#include "SourceCode.h"
#include "FileCount.h"
#include "File.h"
#include <exec/memory.h>
#include <dos/dos.h>
#include <utility/tagitem.h>
#include <proto/exec.h>
#include <proto/dos.h>
#include <cctype>
#include <cstring>
SourceCode::SourceCode(FileCount& fc) :
m_file_count(fc),
m_in_comment(false),
m_source_buf(0),
m_source_size(0)
{
m_line_buf[0] = '\0';
m_lines.reserve(250);
}
SourceCode::~SourceCode()
{
if ( m_source_buf != 0 ) {
IExec->FreeMem(m_source_buf, m_source_size);
}
}
void SourceCode::load()
{
File file;
file.open(m_file_count.getName(), MODE_OLDFILE);
uint32 protection = file.getProtection();
if ( !(protection & FIBF_EXECUTE) ) {
IDOS->SetIoErr(ERROR_OBJECT_WRONG_TYPE);
throw dos_error();
}
m_source_size = file.getLength();
if ( m_source_size == 0 ) {
IDOS->SetIoErr(ERROR_OBJECT_WRONG_TYPE);
throw dos_error();
}
m_source_size += 1; // +1 for end-of-file terminator
m_source_buf = reinterpret_cast<char*>(
IExec->AllocMem(m_source_size, MEMF_ANY));
if ( m_source_buf == 0 ) {
throw std::bad_alloc();
}
m_lines.clear();
char* source = m_source_buf;
try {
while ( file.readString(m_line_buf, MAX_LINE_LEN) > 0 ) {
removeComments();
eatWhite();
int32 line_len = std::strlen(m_line_buf);
if ( line_len > 0 ) {
line_len += 1; // +1 for '\0'
IExec->CopyMem(m_line_buf, source, line_len);
m_lines.push_back(source);
source += line_len;
}
}
}
catch ( ... ) {
IExec->FreeMem(m_source_buf, m_source_size);
m_source_buf = 0;
throw;
}
}
void SourceCode::removeComments()
{
if ( m_file_count.diffMode() ) {
if ( m_line_buf[0] != '<' && m_line_buf[0] != '>' ) {
m_line_buf[0] = '\0';
}
else {
for ( uint32 i = 1;
i < MAX_LINE_LEN && m_line_buf[i] != '\0';
++i ) {
char* c0 = &m_line_buf[i];
char* c1 = &m_line_buf[i+1];
if ( *c0 == '/' && (*c1 == '/' || *c1 == '*') ) {
m_line_buf[0] = '\0';
break;
}
else if ( *c0 == '*' ) {
m_line_buf[0] = '\0';
break;
}
else if ( !std::isspace(*c0) ) {
break;
}
}
}
m_in_comment = false; // no multi-line comments in diff mode
}
for ( uint32 i = 0; i < MAX_LINE_LEN && m_line_buf[i] != '\0'; ++i ) {
char* c0 = &m_line_buf[i];
char* c1 = &m_line_buf[i+1];
if ( m_in_comment ) {
if ( *c0 == '*' && *c1 == '/' ) {
m_in_comment = false;
*c0 = ' ';
*c1 = ' ';
}
else {
*c0 = ' ';
}
}
else {
if ( *c0 == '/' && *c1 == '/' ) {
*c0 = '\0';
break;
}
else if ( *c0 == '/' && *c1 == '*' ) {
m_in_comment = true;
*c0 = ' ';
*c1 = ' ';
}
}
}
m_line_buf[MAX_LINE_LEN - 1] = '\0'; // guarantee null termination
}
void SourceCode::eatWhite()
{
// Convert all line feeds to nulls and white spaces to spaces
for ( uint32 i = 0; i < std::strlen(m_line_buf); ++i ) {
if ( m_line_buf[i] == '\n' ) {
m_line_buf[i] = '\0';
}
else if ( std::isspace(m_line_buf[i]) ) {
m_line_buf[i] = ' ';
}
}
// Remove redundant white space
uint32 stretch = 0;
char* c = &m_line_buf[0];
while ( *c != '\0' ) {
if ( stretch > 0 ) {
if ( std::isspace(*c) ) {
++stretch;
}
else {
char* space = c - stretch;
if ( stretch > 1 ) {
std::strcpy(space + 1, c); // +1 skips the space
}
stretch = 0;
}
}
else {
if ( std::isspace(*c) ) {
++stretch;
}
}
++c;
}
// Remove trailing white space
for ( uint32 i = std::strlen(m_line_buf) - 1;
i >= 0 && std::isspace(m_line_buf[i]);
--i ) {
m_line_buf[i] = '\0';
}
// Remove blank difference mode lines
if ( (m_line_buf[0] == '<' || m_line_buf[0] == '>') &&
std::strlen(m_line_buf) == 1) {
m_line_buf[0] = '\0';
}
}
void SourceCode::count()
{
if ( m_file_count.diffMode() ) {
for ( uint32 i = 0; i < m_lines.size(); ++i ) {
const char* line = m_lines.at(i);
if ( m_file_count.diffMode() ) {
if ( line[0] == '<' ) {
m_file_count -= 1;
}
else if ( line[0] == '>' ) {
m_file_count += 1;
}
}
}
}
else {
m_file_count += m_lines.size();
}
}